糖果

Time Limit: 10 Sec Memory Limit: 128 MB

Description

幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候,lxhgww需要满足小朋友们的K个要求。幼儿园的糖果总是有限的,lxhgww想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。

Input

输入的第一行是两个整数N,K。
  接下来K行,表示这些点需要满足的关系,每行3个数字,X,A,B。
  如果X=1, 表示第A个小朋友分到的糖果必须和第B个小朋友分到的糖果一样多;
  如果X=2, 表示第A个小朋友分到的糖果必须少于第B个小朋友分到的糖果;
  如果X=3, 表示第A个小朋友分到的糖果必须不少于第B个小朋友分到的糖果;
  如果X=4, 表示第A个小朋友分到的糖果必须多于第B个小朋友分到的糖果;
  如果X=5, 表示第A个小朋友分到的糖果必须不多于第B个小朋友分到的糖果;

Output

输出一行,表示lxhgww老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出-1。

Sample Input

5 7
 1 1 2
 2 3 2
 4 4 1
 3 4 5
 5 4 5
 2 3 5
 4 5 1

Sample Output

11

HINT

对于30%的数据,保证 N<=100
  对于100%的数据,保证 N<=100000
  对于所有的数据,保证 K<=100000,1<=X<=5,1<=A, B<=N

Main idea

有若干个小朋友分糖果,要求每个人至少分到一颗糖,给出若干个数之间大小或者等于的限制,求最少需要多少个糖果可以满足条件。

Solution

发现有若干限制大小,那么我们想到了差分约束系统,在两点之间连一条带权边,根据限制条件决定边权。因为要满足所有情况,我们先将所有点入队,跑一遍最长路即可求出答案。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include<bits/stdc++.h>
using namespace std;

const int ONE=200001;
const int INF=2147483640;

int n,m;
int PD,x,y;
int next[ONE],first[ONE],go[ONE],tot;
int w[ONE];
int dist[100001];
int vis[100001],q[1000001],tou,wei;
long long Ans;
int Take_ring[100001];

int get()
{
int res,Q=1; char c;
while( (c=getchar())<48 || c>57)
if(c=='-')Q=-1;
if(Q) res=c-48;
while((c=getchar())>=48 && c<=57)
res=res*10+c-48;
return res*Q;
}

int Add(int u,int v,int z)
{
next[++tot]=first[u]; first[u]=tot; go[tot]=v; w[tot]=z;
}

void PD_same(int x,int y)
{
if(x==y)
{
printf("-1");
exit(0);
}
}

int Spfa()
{
while(tou<wei)
{
int u=q[++tou];
for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(dist[v]<dist[u]+w[e])
{
if(++Take_ring[v]>=n) return 0;
dist[v]=dist[u]+w[e];
if(!vis[v])
{
vis[v]=1;
q[++wei]=v;
}
}
}
vis[u]=0;
}
return 1;
}

int main()
{
n=get(); m=get();
for(int i=1;i<=m;i++)
{
PD=get(); x=get(); y=get();
if(PD==1) Add(x,y,0),Add(y,x,0);
if(PD==2) Add(x,y,1),PD_same(x,y);
if(PD==3) Add(y,x,0);
if(PD==4) Add(y,x,1),PD_same(x,y);
if(PD==5) Add(x,y,0);
}

for(int i=1;i<=n;i++)
{
dist[i]=vis[i]=1;
q[++wei]=i;
}

if(!Spfa())
{
printf("-1");
return 0;
}
for(int i=1;i<=n;i++)
Ans+=(long long)dist[i];
printf("%lld",Ans);

}